package jdbc;

import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

//import com.mysql.jdbc.Connection;
//import com.mysql.jdbc.Driver;


public class SimpleConnectionPool {
	
	private static SimpleConnectionPool ref = null;
	private static int clients;
	private String URI;
	private String dbuser;
	private String dbpass;
	private String drivername;
	private int maxconn;
	private List freeConnections = new ArrayList();

	private SimpleConnectionPool(String URI, 
			String dbuser, 
			String dbpass,
			String drivername, 
			int maxconn) {
		this.URI = URI;
		this.dbuser = dbuser;
		this.dbpass = dbpass;
		this.drivername = drivername;
		this.maxconn = maxconn;

		loadJDBCDriver();
	}

	private void loadJDBCDriver() {
		try {
			//Driver
			Driver driver = (Driver)Class.forName(this.drivername).newInstance();
			DriverManager.registerDriver(driver);
		} catch (Exception e) {
			System.out.println("Can't load/register JDBC driver ");
		}
	}

	static synchronized public SimpleConnectionPool getInstance(String URI, 
			String dbuser, 
			String dbpass, 
			String drivername, 
			int maxconn) {
		if (ref == null) {
			ref = new SimpleConnectionPool(URI, dbuser, dbpass, 
					drivername, maxconn);
		}
		clients++;
		return ref;
	}

	public synchronized Connection getConnection() {
		Connection rescon = null;
		if (!this.freeConnections.isEmpty()) {
			rescon = (Connection)this.freeConnections.get(this.freeConnections.size()-1);
			this.freeConnections.remove(rescon);
			try {
				if (rescon.isClosed()) {
					System.out.println("Removed closed connection!");
					// Try again recursively
					rescon = getConnection();
				}
//			} catch (SQLException e) {
//				System.out.println("Removed closed connection!");
//				// Try again recursively
//				rescon = getConnection();
			} catch (Exception e) {
				System.out.println("Removed closed connection!");
				// Try again recursively
				rescon = getConnection();
			}
		} else {
			rescon = createConnection();
		}
		return rescon;
	}
	
	private Connection createConnection() {
		Connection rescon = null;
		
		try {
			rescon = DriverManager.getConnection(this.URI, this.dbuser, this.dbpass);
			// new connection in connection pool created
			returnConnection(rescon);
		} catch (SQLException e) {
			System.out.println("Cannot create a new connection!");
			rescon = null;
		}
		return rescon;
	}
	
	public synchronized void returnConnection(Connection con) {
		if ((con != null) && (this.freeConnections.size() <= this.maxconn)) {
			this.freeConnections.add(con);
		}
	}
	
	public synchronized void release() {
		Iterator allc = this.freeConnections.iterator();
		while (allc.hasNext()) {
			Connection con = (Connection)allc.next();
			try {
				con.close();
			} catch (SQLException e) {
	 			System.out.println("Cannot close connection!  (Probably already closed?)");
			}
		}
		this.freeConnections.clear();
	}

}
